/*
	Visp is an opensource visual performance application built with Adobe® AIR™.
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
	
	Mike Creighton can be found at http://www.mikecreighton.com	
*/
package com.visp.input
{
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import com.visp.midi.ControllerEvent;
	import com.visp.midi.ProgramChangeEvent;
	import com.visp.midi.NoteEvent;
	import com.visp.midi.MidiManager;
	import com.visp.events.BangEvent;
	import com.visp.events.RangeEvent;
	import com.visp.events.ButtonInputEvent;
	import com.visp.events.SliderInputEvent;
	import com.visp.constants.RendererRange;
	import com.visp.constants.RendererBang;
	import com.visp.constants.FilterRange;
	import com.visp.events.DisplayMouseEvent;
	import com.visp.midi.MidiSettings;

	[Event(name="bangOn", type="com.visp.events.BangEvent")]
	[Event(name="bangOff", type="com.visp.events.BangEvent")]
	[Event(name="range", type="com.visp.events.RangeEvent")]
	[Event(name="up", type="com.visp.events.DisplayMouseEvent")]
	[Event(name="down", type="com.visp.events.DisplayMouseEvent")]
	[Event(name="downMove", type="com.visp.events.DisplayMouseEvent")]
	[Event(name="mouseClick", type="com.visp.events.DisplayMouseEvent")]
		
	public class InputManager extends EventDispatcher
	{
		public static var _instance : InputManager;
		
		private var _midiMgr : MidiManager;
		private var _midiSettings : MidiSettings;
		private var _isEnabled : Boolean;
		
		public static function getInstance() : InputManager
		{
			if(_instance == null){
				_instance = new InputManager();
			}
			return _instance;
		}
		
		public function InputManager()
		{
			super(null);
			enable();
			
			_midiMgr = MidiManager.getInstance();
			_midiMgr.addEventListener(ControllerEvent.CONTROLLER, _handleController);
			_midiMgr.addEventListener(NoteEvent.NOTE_ON, _handleNoteOn);
			_midiMgr.addEventListener(NoteEvent.NOTE_OFF, _handleNoteOff);
			_midiMgr.addEventListener(ProgramChangeEvent.PROGRAM_CHANGE, _handleProgramChange);
			
			_midiSettings = MidiSettings.getInstance();
		}
		
		public function enable() : void
		{
			_isEnabled = true;
		}
		
		public function disable() : void
		{
			_isEnabled = false;
		}
		
		/**
		 * Re-routing input from the preview window events
		 */
		public function handleDisplayMouseInput(e : DisplayMouseEvent) : void
		{
			if(_isEnabled) dispatchEvent(e.clone());
		}
		
		public function handleInternalButtonInput(e : ButtonInputEvent) : void
		{
			if(_isEnabled) {
				var bang : BangEvent;
				if(e.type == ButtonInputEvent.DOWN){
					bang = new BangEvent(BangEvent.BANG_ON, e.id, false);
					bang.velocity = e.velocity;
				} else {
					bang = new BangEvent(BangEvent.BANG_OFF, e.id, false);
				}
				dispatchEvent(bang);
			}
		}
		
		public function handleInternalSliderInput(e : SliderInputEvent) : void
		{
			if(_isEnabled) {
				var range : RangeEvent = new RangeEvent(RangeEvent.RANGE, e.id, e.value, false);
				dispatchEvent(range);
			}
		}
		
		private function _handleNoteOn(e : NoteEvent) : void
		{
			if(_isEnabled) {
				var inputId : int = _midiSettings.getInputIdByNote(e.pitch);
				// The inputId will be equal to a RendererBang constant if set
				if(inputId){
					var bangOn : BangEvent = new BangEvent(BangEvent.BANG_ON, inputId, true);
					bangOn.velocity = e.velocity;
					dispatchEvent(bangOn);
				}
			}
		}
		
		private function _handleNoteOff(e : NoteEvent) : void
		{
			if(_isEnabled) {
				var inputId : int = _midiSettings.getInputIdByNote(e.pitch);
				// The inputId will be equal to a RendererBang constant if set
				if(inputId){
					var bangOff : BangEvent = new BangEvent(BangEvent.BANG_OFF, inputId, true);
						dispatchEvent(bangOff);
				}
			}
		}
		
		/**
		 * Interprets and re-routes program change events from the MidiManager
		 */
		private function _handleProgramChange(e : ProgramChangeEvent) : void
		{
			// trace("Program change: " + e.id);
		}
		
		private function _handleController(e : ControllerEvent) : void
		{
			if(_isEnabled) {
				var inputId : int = _midiSettings.getInputIdByController(e.id);
				if(inputId) {
					dispatchEvent(new RangeEvent(RangeEvent.RANGE, inputId, e.value, true));
				}
			}
		}
	}
}